package oss

import (
	"errors"
	"mime/multipart"
	"os"
	"path/filepath"
	"rabbit_love/src/conf"
	"rabbit_love/src/utils/local"
	"strconv"
	"strings"
	"time"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	log "github.com/cihub/seelog"
)

var ContentType map[string]string = map[string]string{
	".jpe":  "image/jpeg",
	".jpeg": "image/jpeg",
	".jpg":  "image/jpeg",
	".png":  "image/png",
}

// fileBucket 存储空间实例
var fileBucket *oss.Bucket

// InitFileBucket 获取 oss 的 bucket 实例
func InitFileBucket(bucketName string, endPoint string, keyID string, keySecret string) error {
	var (
		client *oss.Client
		err    error
	)
	client, err = oss.New(endPoint, keyID, keySecret)
	if err != nil {
		log.Error("initFileBucket client Error:", err.Error())
		return err
	}
	fileBucket, err = client.Bucket(bucketName)
	if err != nil {
		log.Error("initFileBucket bucket Error:", err.Error())
		return err
	}
	log.Info("initFileBucket success.")
	return nil
}

/* ------ 相关函数 ------ */

/*
GetFileSize 获取文件大小
*/
func GetFileSize(filename string) string {
	var result float32
	filepath.Walk(filename, func(path string, f os.FileInfo, err error) error {
		result = float32(f.Size())
		return nil
	})
	return strconv.FormatFloat(float64(result/1000), 'f', 1, 64)
}

// IsObjectExist 判断 oss 中文件是否存在
func IsObjectExist(fPath string) bool {
	isExist, err := fileBucket.IsObjectExist(fPath)
	if err != nil {
		log.Error(" IsObjectExist ", fPath, " Error: ", err.Error())
		return false
	}
	return isExist
}

// GetContentType 获取文件类型
func GetContentType(fileName string) (fileType, contentType string) {
	contentType = "application/octet-stream"
	strArr := strings.Split(fileName, ".")
	fileType = "."
	if len(strArr) > 1 {
		fileType = "." + strArr[len(strArr)-1]
	}
	if value, ok := ContentType[fileType]; ok {
		contentType = value
	}
	return fileType, contentType
}

/* ------ 文件 上传、删除等 操作 ------ */

// SaveFileToOSS 将文件同步到 oss
func SaveFileToOSS(fileMultipart *multipart.FileHeader) (string, error) {
	var (
		err  error
		file multipart.File
	)

	file, err = fileMultipart.Open()
	if err != nil {
		return "", errors.New("文件无法打开")
	}
	defer file.Close()

	// 上传文件
	fileType, contentType := GetContentType(fileMultipart.Filename)
	if fileType == "." {
		return "", errors.New("文件格式错误")
	}
	option := oss.ContentType(contentType)

	fileName := strconv.FormatInt(time.Now().Unix(), 10) + local.GetRandomBoth(4) + fileType

	var (
		filtPath string = conf.OSSSaveBucket + "/" + time.Now().Format("2006-01-02") + "/" + fileName
	)
	err = fileBucket.PutObject(filtPath, file, option)
	if err != nil {
		log.Error("saveFileToOSS ", filtPath, " Error: ", err.Error())
		return "", errors.New("文件上传失败")
	}

	log.Info("saveFileToOSS ", filtPath, " success.")
	return filtPath, nil
}

// DelFile 删除文件
func DelFile(filePath string) {
	// 判断文件是否存在。
	if isExist := IsObjectExist(filePath); !isExist {
		log.Error("delFile file no exist ", filePath)
		return
	}

	// 删除 oss 里的文件
	err := fileBucket.DeleteObject(filePath)
	if err != nil {
		log.Error("delFile ", filePath, " Error: ", err.Error())
		return
	}

	return
}

// GetImgURL 获取临时授权下载 url 有效时间 2 小时。
func GetImgURL(fPath string) string {
	var (
		URL string
		err error
	)
	URL, err = fileBucket.SignURL(fPath, oss.HTTPGet, 60*60*2, oss.Process("image/format,png"))
	if err != nil {
		log.Error("-- GetImgURL ", fPath, " Error: ", err.Error())
	}
	return URL
}
